/*
 * Copyright (c) Huawei Device Co., Ltd. 2023. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef COMMON_UTILS_H
#define COMMON_UTILS_H

#include <string>
#include <vector>
#include <iostream>
#include <iomanip>

namespace OHOS {
namespace SE {
// the SA ID for secure element service.
constexpr uint16_t SE_MANAGER_SYS_ABILITY_ID = 1141;

// the string length in hex byte format.
constexpr uint8_t HEX_BYTE_LEN = 2;

// shifting bits of half byte.
constexpr uint8_t HALF_BYTE_SHIFT = 4;

// shifting bits of one byte.
constexpr uint8_t ONE_BYTE_SHIFT = 8;

// shifting bits of two bytes
constexpr uint8_t TWO_BYTES_SHIFT = 16;

// the APDU response status word bytes
constexpr uint8_t APDU_SW_BYTES = 2;

// the max APDU response bytes
constexpr uint16_t MAX_APDU_RESP_BYTES = 512;

// the APDU command bytes in ISO7816
constexpr uint8_t CMD_HEAD_BYTES = 4;

// the class index of APDU command in ISO7816
constexpr uint8_t CMD_HEAD_CLA = 0;

// the instruction index of APDU command in ISO7816
constexpr uint8_t CMD_HEAD_INS = 1;

// the p1 index of APDU command in ISO7816
constexpr uint8_t CMD_HEAD_P1 = 2;

// the p2 index of APDU command in ISO7816
constexpr uint8_t CMD_HEAD_P2 = 3;

// the LC index of APDU command in ISO7816
constexpr uint8_t CMD_LC_INDEX = 4;

// no LC, the LE index of APDU command in ISO7816
constexpr uint8_t CMD_NO_LC_LE_INDEX = 4;

// the payload data index of APDU command in ISO7816
constexpr uint8_t CMD_PAYLOAD_DATA_INDEX = 5;

// the min size of aid.
constexpr uint8_t AID_MIN_SIZE = 5;

// the max size of aid.
constexpr uint8_t AID_MAX_SIZE = 16;

// the basic chennel id value.
constexpr uint8_t BASIC_CHANNEL_ID = 0;

// The standard name of eSE.
static const std::string SE_NAME_ESE = "eSE";

// The standard name of SIM
static const std::string SE_NAME_SIM = "SIM";

enum ErrorCode : const int {
    SE_SUCCESS = 0,

    // secure element exception
    SE_ILLEGAL_STATE_ERROR = 101,
    SE_NO_SUCH_ELEMENT_ERROR,
    SE_IO_ERROR,
    SE_NULL_POINTER_ERROR,
    SE_ILLEGAL_PARAMETER_ERROR,
    SE_SECURITY_ERROR,
    SE_CHANNEL_NOT_AVAILABLE_ERROR,
    SE_ILLEGAL_REFERENCE_ERROR,
    SE_OPERATION_NOT_SUPPORTED_ERROR,
    SE_GENERAL_ERROR,

    // access control exception
    SE_ACCESS_CONTROL_ERROR = 201,

    // IPC token error
    SE_IPC_TOKEN_ERROR = 301,

    // init SA failed
    SE_INIT_FAILURE = 401,
};

class CommonUtils {
public:
    /**
     * @brief convert byte array to hex string.
     * @param src the byte array data to be converted.
     * @param length the data length.
     * @return the converted hex string.
     */
    static std::string BytesArrayToHexString(const uint8_t *src, uint32_t length);

    /**
     * @brief convert hex string to byte array.
     * @param src the hex string to be converted.
     * @param bytes the output byte array.
     * @return the converted byte array.
     */
    static void HexStringToBytesArray(const std::string &src, std::vector<uint8_t> &bytes);

    /**
     * @brief get the hex string length, the bytes.
     * @param src the hex string to calculate the length.
     * @return the hex string lenght, the bytes.
     */
    static uint32_t GetHexStringLength(const std::string &src);

    /**
     * @brief get the specific byte from the hex string.
     * @param src the hex string to get the data.
     * @param index the index to get the byte.
     * @return the specific byte from the hex string.
     */
    static uint8_t GetHexStrByte(const std::string &src, uint32_t index);

    /**
     * @brief convert the hex byte to string.
     * @param src the the hex byte to convert.
     * @return the converted string.
     */
    static std::string UnsignedCharToHexString(const uint8_t src);

    /**
     * @brief get the response status word first byte from the reponse data of secure element.
     * @param apduResp the reponse data of secure element.
     * @return the response status word first byte.
     */
    static uint8_t GetApduRespSw1(const std::string &apduResp);

    /**
     * @brief get the response status word second byte from the reponse data of secure element.
     * @param apduResp the reponse data of secure element.
     * @return the response status word second byte.
     */
    static uint8_t GetApduRespSw2(const std::string &apduResp);

    /**
     * @brief check if the status word is 9000 or not.
     * @param apduResp the reponse data of secure element.
     * @return true if the status word is 9000, false otherwise.
     */
    static bool IsApduRespSuccess(const std::string &apduResp);

    /**
     * @brief covert int to ErrorCode
     * @param statusCode the statusCode of secure element.
     * @return ErrorCode.
     */
    static ErrorCode IntToErrorCode(const int &statusCode);

    /**
     * @brief Generate a unique tag based on called tokenID and PID..
     * @return the unique tag for calling business.
     */
    static std::string GetUniqueTag();

    /**
     * @brief Returns the date and time stamp, in milliseconds, e.g 1970-01-01 00:00:00
     * @return Returns the time, in string
     */
    static std::string GetLocalTimeStampWithDate();

    /**
     * @brief Returns the file size with uint32
     * @return Returns the file size
     */
    static uint32_t GetFileSize(const std::string &fileNamePath);
};
}  // namespace SE
}  // namespace OHOS
#endif // !COMMON_UTILS_H
